﻿using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;

namespace Vulcano.Helpers.enUSParser
{
    public class NextNYears :DateTimeParserBase,IDateTimeParser
    {
        
        public Regex Regex()
        {
            return new Regex(@"next +([2-9]\d*) +years");
        }
        
        public DateTime Parse(Match m)
        {
            var val = int.Parse(m.Groups[1].Value);
            return today.AddYears(val);
        }
    }

    public class NextNWeeks : DateTimeParserBase, IDateTimeParser
    {

        public Regex Regex()
        {
            return new Regex(@"next +([2-9]\d*) +weeks");
        }

        public DateTime Parse(Match m)
        {
            var val = int.Parse(m.Groups[1].Value);
            return today.AddDays(val * 7);
        }
    }

    public class NextNMonths : DateTimeParserBase, IDateTimeParser
    {

        public Regex Regex()
        {
            return new Regex(@"next +([2-9]\d*) +months");
        }

        public DateTime Parse(Match m)
        {
            var val = int.Parse(m.Groups[1].Value);
            return today.AddMonths(val);
        }
    }
    
    public class NextNDays : DateTimeParserBase, IDateTimeParser
    {

        public Regex Regex()
        {
            return new Regex(@"next +([2-9]\d*) +days");
        }

        public DateTime Parse(Match m)
        {
            var val = int.Parse(m.Groups[1].Value);
            return today.AddDays(val);
        }
    }

    public class NextLastWeekMonthYear : DateTimeParserBase, IDateTimeParser
    {

        public Regex Regex()
        {
            return new Regex(@"(last|next) *(week|year|month)");
        }

        public DateTime Parse(Match m)
        {
            int direction = (m.Groups[1].Value == "last") ? -1 : 1;
            switch (m.Groups[2].Value)
            {
                case "week":
                    return today.AddDays(7 * direction);
                case "year":
                    return today.AddYears(direction);
                case "month":
                    return today.AddMonths(direction);
            }
            return DateTime.MinValue;
        }
    }

    public class Now : DateTimeParserBase, IDateTimeParser
    {

        public Regex Regex()
        {
            return new Regex(@"now");
        }

        public DateTime Parse(Match m)
        {
            return DateTime.Now;
        }
    }

    public class Tomorrow : DateTimeParserBase, IDateTimeParser
    {

        public Regex Regex()
        {
            return new Regex(@"tomorrow");
        }

        public DateTime Parse(Match m)
        {
            return today.AddDays(1);
        }
    }

    public class Yesterday : DateTimeParserBase, IDateTimeParser
    {

        public Regex Regex()
        {
            return new Regex(@"yesterday");
        }

        public DateTime Parse(Match m)
        {
            return today.AddDays(-1);
        }
    }

    public class Today : DateTimeParserBase, IDateTimeParser
    {

        public Regex Regex()
        {
            return new Regex(@"today");
        }

        public DateTime Parse(Match m)
        {
            return today;
        }
    }
    
    public class NSecondsMinutesHoursDaysWeeksMonthsYearsAgo : DateTimeParserBase, IDateTimeParser
    {

        public Regex Regex()
        {
            return new Regex(@"([1-9]\d*) *(second(s)?|minute(s)?|hour(s)?|day(s)?|week(s)?|month(s)?|year(s)?) +ago");
        }

        public DateTime Parse(Match m)
        {
            var val = int.Parse(m.Groups[1].Value);
            switch (m.Groups[2].Value)
            {
                case "second":
                case "seconds":
                    return DateTime.Now.AddSeconds(-val);
                case "minute":
                case "minutes":
                    return DateTime.Now.AddMinutes(-val);
                case "hour":
                case "hours":
                    return DateTime.Now.AddHours(-val);
                case "day":
                case "days":
                    return today.AddDays(-val);
                case "week":
                case "weeks":
                    return today.AddDays(-val*7);
                case "month":
                case "months":
                    return today.AddMonths(-val);
                case "year":
                case "years":
                    return today.AddYears(-val);
            }
            return DateTime.MinValue;

        }

    }

    public class NextWeekDay : DateTimeParserBase, IDateTimeParser
    {
        List<string> dayList = new List<string>() { "sund", "mond", "tues", "wedn", "thur", "frid", "satu" };
        public Regex Regex()
        {
            return new Regex(String.Format(@"(last|next) *({0}).*", String.Join("|", dayList.ToArray())));
        }

        public DateTime Parse(Match m)
        {
            var val = m.Groups[2].Value;
            var direction = (m.Groups[1].Value == "last") ? -1 : 1;
            var dayOfWeek = dayList.IndexOf(val.Substring(0, 4));
            if (dayOfWeek >= 0)
            {
                var diff = direction * (dayOfWeek - (int)DateTime.Today.DayOfWeek);
                if (diff <= 0)
                {
                    diff = 7 + diff;
                }
                return DateTime.Today.AddDays(direction * diff);
            }
            return DateTime.MinValue;
        }
    }

}
